#ifndef SIMPLE_IO_HANDLE_COMMON_H
#define SIMPLE_IO_HANDLE_COMMON_H

#include <cstddef> // std::nullptr_t
#include <type_traits> // std::true_type
#include <memory> // std::unique_ptr

#include "simple/support/enum_flags_operators.hpp" // support::define_enum_flags_operators

namespace simple::io
{
	enum class operation
	{
		none,
		read = 1u,
		write = 1u << 1
	};

	// TODO: move to simple::support
	template <typename Config>
	class custom_deleter
	{
		using handle = typename Config::handle_t;
		public:
		class pointer
		{
			handle h;
			public:
			pointer() noexcept;
			pointer(handle) noexcept;
			pointer(std::nullptr_t) noexcept;

			[[nodiscard]] // cause std is dumb, what can I say
			bool operator==(pointer) const noexcept;
			[[nodiscard]]
			bool operator!=(pointer) const noexcept;

			[[nodiscard]]
			operator handle() const noexcept;
			[[nodiscard]]
			explicit operator bool() const noexcept;
		};

		void operator ()(pointer) const noexcept;
	};

	// TODO: move to simple::support
	template <typename Config>
	using custom_unique_ptr = std::unique_ptr<
		typename custom_deleter<Config>::pointer,
		custom_deleter<Config>
	>;

} // namespace simple::io

template<> struct
simple::support::define_enum_flags_operators<simple::io::operation>
	: std::true_type {};

#endif /* end of include guard */
